import { ITERATE_KEY, TriggerOpTypes,TrackOpTypes } from "../utils";
import { targetMap, ReactiveEffect, activeEffect } from "./effect";

// 更新类型影响到的收集类型的依赖对应关系
export const triggerTypeMap = {
  [TriggerOpTypes.SET]: [
    TrackOpTypes.GET,
  ],
  [TriggerOpTypes.ADD]: [
    TrackOpTypes.GET,
    TrackOpTypes.HAS,
    TrackOpTypes.ITERATE
  ],
  [TriggerOpTypes.DELETE]: [
    TrackOpTypes.GET,
    TrackOpTypes.HAS,
    TrackOpTypes.ITERATE
  ]
}

/**
 * 
 * @param target 
 * @param type 触发派发更新的类型，包括SET、ADD、DELETE
 * @param key 
 */
export function trigger(target: any, type: TriggerOpTypes, key: string | symbol) {
  const effects = getEffectFns(target, type, key)
  if (effects?.size) {
    effects.forEach(effect => {
      // 如果是正在执行的effect，则不再次执行
      if(effect === activeEffect) {
        return
      }
      if (effect.scheduler) {
        effect.scheduler(effect)
      } else {
        effect.run()
      }
    })
  }
}

function getEffectFns(target: any, type: TriggerOpTypes, key: string | symbol) {
  let propMap = targetMap.get(target)
  if (!propMap) {
    return
  }
  const keys = [key]
  if(type === TriggerOpTypes.ADD || type === TriggerOpTypes.DELETE) {
    keys.push(ITERATE_KEY)
  }

  const effectFns = new Set<ReactiveEffect>()
  keys.forEach(key => {
    const typeMap = propMap.get(key)
    if (!typeMap) {
      return
    }
    const trackTypes = triggerTypeMap[type]
    trackTypes.forEach(trackType => {
      const effects = typeMap.get(trackType)
      if (effects) {
        effects.forEach(effect => {
          effectFns.add(effect)
        })
      }
    })
  })
  return effectFns
}